1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.google.common.collect;
16
17 import com.google.common.annotations.GwtCompatible;
18
19 import java.util.AbstractCollection;
20 import java.util.AbstractSet;
21 import java.util.Collection;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.annotation.Nullable;
27
28
29
30
31
32
33 @GwtCompatible
34 abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
35
36 @Override
37 public boolean containsRow(@Nullable Object rowKey) {
38 return Maps.safeContainsKey(rowMap(), rowKey);
39 }
40
41 @Override
42 public boolean containsColumn(@Nullable Object columnKey) {
43 return Maps.safeContainsKey(columnMap(), columnKey);
44 }
45
46 @Override
47 public Set<R> rowKeySet() {
48 return rowMap().keySet();
49 }
50
51 @Override
52 public Set<C> columnKeySet() {
53 return columnMap().keySet();
54 }
55
56 @Override
57 public boolean containsValue(@Nullable Object value) {
58 for (Map<C, V> row : rowMap().values()) {
59 if (row.containsValue(value)) {
60 return true;
61 }
62 }
63 return false;
64 }
65
66 @Override
67 public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
68 Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
69 return row != null && Maps.safeContainsKey(row, columnKey);
70 }
71
72 @Override
73 public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
74 Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
75 return (row == null) ? null : Maps.safeGet(row, columnKey);
76 }
77
78 @Override
79 public boolean isEmpty() {
80 return size() == 0;
81 }
82
83 @Override
84 public void clear() {
85 Iterators.clear(cellSet().iterator());
86 }
87
88 @Override
89 public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
90 Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
91 return (row == null) ? null : Maps.safeRemove(row, columnKey);
92 }
93
94 @Override
95 public V put(R rowKey, C columnKey, V value) {
96 return row(rowKey).put(columnKey, value);
97 }
98
99 @Override
100 public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
101 for (Table.Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
102 put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
103 }
104 }
105
106 private transient Set<Cell<R, C, V>> cellSet;
107
108 @Override
109 public Set<Cell<R, C, V>> cellSet() {
110 Set<Cell<R, C, V>> result = cellSet;
111 return (result == null) ? cellSet = createCellSet() : result;
112 }
113
114 Set<Cell<R, C, V>> createCellSet() {
115 return new CellSet();
116 }
117
118 abstract Iterator<Table.Cell<R, C, V>> cellIterator();
119
120 class CellSet extends AbstractSet<Cell<R, C, V>> {
121 @Override
122 public boolean contains(Object o) {
123 if (o instanceof Cell) {
124 Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
125 Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
126 return row != null && Collections2.safeContains(
127 row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
128 }
129 return false;
130 }
131
132 @Override
133 public boolean remove(@Nullable Object o) {
134 if (o instanceof Cell) {
135 Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
136 Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
137 return row != null && Collections2.safeRemove(
138 row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
139 }
140 return false;
141 }
142
143 @Override
144 public void clear() {
145 AbstractTable.this.clear();
146 }
147
148 @Override
149 public Iterator<Table.Cell<R, C, V>> iterator() {
150 return cellIterator();
151 }
152
153 @Override
154 public int size() {
155 return AbstractTable.this.size();
156 }
157 }
158
159 private transient Collection<V> values;
160
161 @Override
162 public Collection<V> values() {
163 Collection<V> result = values;
164 return (result == null) ? values = createValues() : result;
165 }
166
167 Collection<V> createValues() {
168 return new Values();
169 }
170
171 Iterator<V> valuesIterator() {
172 return new TransformedIterator<Cell<R, C, V>, V>(cellSet().iterator()) {
173 @Override
174 V transform(Cell<R, C, V> cell) {
175 return cell.getValue();
176 }
177 };
178 }
179
180 class Values extends AbstractCollection<V> {
181 @Override
182 public Iterator<V> iterator() {
183 return valuesIterator();
184 }
185
186 @Override
187 public boolean contains(Object o) {
188 return containsValue(o);
189 }
190
191 @Override
192 public void clear() {
193 AbstractTable.this.clear();
194 }
195
196 @Override
197 public int size() {
198 return AbstractTable.this.size();
199 }
200 }
201
202 @Override public boolean equals(@Nullable Object obj) {
203 return Tables.equalsImpl(this, obj);
204 }
205
206 @Override public int hashCode() {
207 return cellSet().hashCode();
208 }
209
210
211
212
213 @Override public String toString() {
214 return rowMap().toString();
215 }
216 }